#include "nettchannel.h"

#include <time.h>
#ifdef WIN32
#define usleep(x) Sleep(x)
#endif
#ifdef __linux__
#include <stdexcept>
#endif // __linux__
#include "pfunc.h"
#include "datadef.h"
#include "business_def.h"
#include "socketclient.h"
#include "Log.h"

NetTChannel::NetTChannel(int tid_)
    : TranChannel(tid_)
{
    init(tid_);
}

NetTChannel::~NetTChannel()
{
    running = false;
}

void* NetTChannel::run()
{
    if (NULL == ptr_client) 
	{
		CLogger::createInstance()->Log(MsgError,
			"NetTChannel start fail for ptr_client is NULL"
			",[%s %s %d]!"
			, __FILE__, __FUNCTION__, __LINE__);
		return 0;
	}
	while(running)
	{
		if (ptr_client->isConnect()) 
        {
            //读取数据
            read();
			//进行数据写入
			write();
		}else{
            ptr_client->disConnect();
            bool linkf = ptr_client->connect();
			if (!linkf)
			{
				sleep(15);  //连接不上,等待15秒
			}else{
                WriteDataS->clear();
            }
		}
		usleep(1);
	}
    return NULL;
}

void NetTChannel::init(int tid_)
{
    running = true;
    BusinessDef *ptrBDef = BusinessDef::getInstance();
    if(ptrBDef->getNetInfoByTID(tid_,netargs))
    {
        ptr_client = new SocketClinet(netargs.ip,netargs.port);
    }
    heartBeatWrite = static_cast<unsigned int>(time(NULL));
}

void NetTChannel::read()
{
    //读取帧数据
    switch (netargs.type)
    {
    case 1:
    {
        //数据有特定帧头和结尾,做分帧处理
        int ret = ptr_client->Read(rdc_data);
        if (ret > 0)
        {
            unsigned char * buff = rdc_data.Buf;
            int start_pos = 0;
            unsigned char ctype = 0;
            // printf("tran read:\n");
            for (int i = 0; i < rdc_data.len; ++i)
            {
                // printf("%02X ",buff[i]);
                if (buff[i] > 0xf0) 
                {
                    if (buff[i] == 0xff) 
                    {
                        if (ctype) 
                        {
                            ctype = 0;
                            ChannelCmd rdata(buff + start_pos, i - start_pos + 1);
                            ReadDatas->add(rdata);
                            start_pos = i + 1;
                        }
                    }
                    else {
                        ctype = buff[i];
                        start_pos = i;
                    }
                }
            }
            // printf("\n");
            buff = NULL;
            if (start_pos < rdc_data.len)
            {
                RDClient _newrd(rdc_data.Buf + start_pos, rdc_data.len - start_pos);
                rdc_data = _newrd;
            }
            else {
                rdc_data.len = 0;
            }
        }
        //数据帧解析
        while (ReadDatas->getFirst(rddata))
        {
            unsigned char * pBuf = new unsigned char[rddata.len];
            int nLen = pyfree::uncode(rddata.Buf, rddata.len, pBuf);//反序列化处理
            this->AddFrame(pBuf, nLen);
            delete[] pBuf;
            pBuf = NULL;
            ReadDatas->removeFirst();
        }
    }
    break;
    case 2:
    {
        //直接读取,不用做分帧处理,ACSII字段
        char buf[256] = { 0 };
        int len = ptr_client->Read(buf, 256);
        if (len > 0) 
        {
            ChannelCmd rdata((unsigned char*)buf, len);
            ReadDatas->add(rdata);
        }
        //数据帧解析
        if (ReadDatas->getFirst(rddata))
        {
            this->AddFrame(rddata.Buf, rddata.len);
            ReadDatas->removeFirst();
        }
    }
    break;
    default:
        CLogger::createInstance()->Log(MsgError,
            "Exception for Reading and Parsing is undef NetType(%d),[%s %s %d]!"
            , netargs.type
            , __FILE__, __FUNCTION__, __LINE__);
        break;
    }
}

void NetTChannel::write()
{
    unsigned char buf[512] = { 0 };
    int len = this->getBuffer(buf,512);
    if (len < 0 && (heartBeatWrite+10)<static_cast<unsigned int>(time(NULL))) 
    {
        len = this->getHeartBeatBuffer(buf,512);
    }
    if (len > 0) {
        switch (netargs.type)
        {
        case 1:
        {
            int cacheLen = 2 * len + 1;
            unsigned char* _buf = new unsigned char[cacheLen];
            memset(_buf, 0, cacheLen);
            int nLen = pyfree::code(buf, len, _buf);//序列化处理
            // printf("tran:\n");
            // for (int j = 0; j < nLen; j++) {
            //     printf("%02X", static_cast<unsigned char>(_buf[j]));
            // }
            // printf("\n");
            int ret = ptr_client->Write((const char*)_buf, nLen);
            if (ret != nLen) {
                CLogger::createInstance()->Log(MsgInfo,
                    "send point data: %d, buf %d. [%s %s %d]"
                    , nLen, ret
                    , __FILE__, __FUNCTION__, __LINE__);
            }
            else {
                heartBeatWrite = static_cast<unsigned int>(time(NULL));
            }
            delete[] _buf;
            _buf = NULL;
        }
        break;
        case 2:
        {
            int ret = ptr_client->Write((const char*)buf, len);
            if (ret != len) {
                CLogger::createInstance()->Log(MsgInfo,
                    "send point data: %d, buf %d. [%s %s %d]"
                    , len, ret
                    , __FILE__, __FUNCTION__, __LINE__);
            }
            else {
                heartBeatWrite = static_cast<unsigned int>(time(NULL));
            }
        }
        break;
        default:
            CLogger::createInstance()->Log(MsgError,
                "Exception for Write data and unkown NetType(%d),[%s %s %d]!"
                , netargs.type
                , __FILE__, __FUNCTION__, __LINE__);
            break;
        }

    }
}

int NetTChannel::getBuffer(unsigned char * _buf, int size)
{
	switch (netargs.ptype)
	{
	case 1:
		return getBufferTran(_buf,size);
	case 2:
		return getBufferDef(_buf,size);
	case 3:
		return getBufferDefList(_buf,size);
	default:
		return 0;
	}
};

int NetTChannel::getHeartBeatBuffer(unsigned char * buf, int size)
{
	if (NULL != buf) {
		int idx = 0;

		buf[idx++] = 0xF9;		//0-STX
								//信息长度
		buf[idx++] = 0xf0;		//1-Len_L
		buf[idx++] = 0xf0;		//2-Len_H
		//time
		unsigned int cur_time = static_cast<unsigned int>(time(NULL));
		buf[idx++] = static_cast<unsigned char>(cur_time & 0xff);
		buf[idx++] = static_cast<unsigned char>((cur_time >> 8) & 0xff);
		buf[idx++] = static_cast<unsigned char>((cur_time >> 16) & 0xff);
		buf[idx++] = static_cast<unsigned char>((cur_time >> 24) & 0xff);
		//comment len
		buf[1] = static_cast<unsigned char>(idx & 0xff);
		buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);

		unsigned char m_end = 0xFF;
		memcpy(buf + idx, &m_end, 1);
		idx++;
		return idx;
	}
	else {
		return 0;
	}
};

int NetTChannel::AddFrame(const unsigned char *buf, int len)
{
	switch (netargs.ptype)
	{
	case 1:
		return AddFrameTran(buf,len);
	case 2:case 3:
		return AddFrameDef(buf,len);
	default:
		Print_WARN("AddFrame error for protoType isn't map\n");
		return 0;
	}
};

int NetTChannel::getBufferDef(unsigned char * buf, int size)
{
	ChannelToTransmit it;
	if(WriteDataS->pop(it))
	{
		try{
			int idx = 0;
			//unsigned char buf[512] = {0};

			buf[idx++] = 0xF7;		//0-STX
			//信息长度
			buf[idx++] = 0xf0;		//1-Len_L
			buf[idx++] = 0xf0;		//2-Len_H
			//时间
			//buf[idx++] = static_cast<unsigned char>(it.evtTimeS & 0xff);
			//buf[idx++] = static_cast<unsigned char>((it.evtTimeS >> 8) &0xff);
			//buf[idx++] = static_cast<unsigned char>((it.evtTimeS >> 16) &0xff);
			//buf[idx++] = static_cast<unsigned char>((it.evtTimeS >> 24) &0xff);
			//buf[idx++] = static_cast<unsigned char>(it.evtTimeMS & 0xFF);		//时间毫秒值

			//pid
			buf[idx++] = static_cast<unsigned char>(it.pID & 0xff);
			buf[idx++] = static_cast<unsigned char>((it.pID >> 8) & 0xff);
			buf[idx++] = static_cast<unsigned char>((it.pID >> 16) & 0xff);
			buf[idx++] = static_cast<unsigned char>((it.pID >> 24) & 0xff);
			//
			buf[idx++] = static_cast<unsigned char>(it.pType & 0xff);
			//val
			unsigned char*vavch = (unsigned char*)&(it.val);
			buf[idx++] = vavch[3];
			buf[idx++] = vavch[2];
			buf[idx++] = vavch[1];
			buf[idx++] = vavch[0];
			vavch = NULL;
			//taskid
			unsigned long tranTaskID = it.changeF ? it.taskID : 0;
			buf[idx++] = static_cast<unsigned char>(tranTaskID & 0xff);
			buf[idx++] = static_cast<unsigned char>((tranTaskID >> 8) & 0xff);
			buf[idx++] = static_cast<unsigned char>((tranTaskID >> 16) & 0xff);
			buf[idx++] = static_cast<unsigned char>((tranTaskID >> 24) & 0xff);
			//comment len
			buf[1] = static_cast<unsigned char>(idx & 0xff);
			buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);

			unsigned char m_end = 0xFF;
			memcpy(buf+idx,&m_end,1);
			idx++;

			if (it.changeF&&it.taskID>0) 
			{
				CLogger::createInstance()->Log(MsgInfo,
					"TaskID[%lu] and up_node[4] getBufferDef, time(%s),pID(%d),pType(%d),val(%.3f)"
					, it.taskID, pyfree::getCurrentTime().c_str()
					, it.pID, static_cast<int>(it.pType), it.val);
			}
			// printf("send len(%d):\n", idx);
			// for (int i = 0; i < idx; i++)
			// {
			// 	printf("%02X", buf[i]);
			// }
			// printf("\n");
			return idx;
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"write item info to socket failed! have error[%s]. [%s %s %d]"
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...) {
			//printf_s("write item info to socket failed! have error. \r\n");
			CLogger::createInstance()->Log(MsgFatal,
				"write item info to socket failed! have error. [%s %s %d]"
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
};

int NetTChannel::getBufferDefList(unsigned char * buf, int size)
{
	std::queue<ChannelToTransmit> its;
	if (WriteDataS->getList(its,10))
	{
		try
		{
			int idx = 0;
			//unsigned char buf[512] = {0};

			buf[idx++] = 0xF8;		//0-STX
									//信息长度
			buf[idx++] = 0xf0;		//1-Len_L
			buf[idx++] = 0xf0;		//2-Len_H
			//
			buf[idx++] = 0x00;		//size_L
			buf[idx++] = 0x00;		//size_H
			int sizeW = 0;
			while (!its.empty())
			{
				ChannelToTransmit it = its.front();
				//pid
				buf[idx++] = static_cast<unsigned char>(it.pID & 0xff);
				buf[idx++] = static_cast<unsigned char>((it.pID >> 8) & 0xff);
				buf[idx++] = static_cast<unsigned char>((it.pID >> 16) & 0xff);
				buf[idx++] = static_cast<unsigned char>((it.pID >> 24) & 0xff);
				//
				buf[idx++] = static_cast<unsigned char>(it.pType & 0xff);
				//val
				unsigned char*vavch = (unsigned char*)&(it.val);
				buf[idx++] = vavch[3];
				buf[idx++] = vavch[2];
				buf[idx++] = vavch[1];
				buf[idx++] = vavch[0];
				vavch = NULL;
				//taskid
				unsigned long tranTaskID = it.changeF ? it.taskID : 0;
				buf[idx++] = static_cast<unsigned char>(tranTaskID & 0xff);
				buf[idx++] = static_cast<unsigned char>((tranTaskID >> 8) & 0xff);
				buf[idx++] = static_cast<unsigned char>((tranTaskID >> 16) & 0xff);
				buf[idx++] = static_cast<unsigned char>((tranTaskID >> 24) & 0xff);
				sizeW += 1;//实际写入长度
				//
				if (it.changeF&&it.taskID > 0) 
				{
					CLogger::createInstance()->Log(MsgInfo,
						"TaskID[%lu] and up_node[4] getBufferDefList, time(%s),pID(%d),pType(%d),val(%.3f)"
						, it.taskID, pyfree::getCurrentTime().c_str()
						, it.pID, static_cast<int>(it.pType), it.val);
				}
				//
				its.pop();
			}
			//comment len
			buf[1] = static_cast<unsigned char>(idx & 0xff);
			buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);
			//ponit size
			buf[3] = static_cast<unsigned char>(sizeW & 0xff);
			buf[4] = static_cast<unsigned char>((sizeW >> 8) & 0xff);
			//
			unsigned char m_end = 0xFF;
			memcpy(buf + idx, &m_end, 1);
			idx++;
			
			// printf(".....................%d.........................\n",idx);
			//
			return idx;
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"write items info to socket failed! have error %s. [%s %s %d]"
				,e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
};

int NetTChannel::AddFrameDef(const unsigned char *pBuf, int len)
{
	try {
		unsigned char type = pBuf[0];
		int idx = 1;
		switch (type)
		{
		case 0XF5://查询
		{
			int rlen = pBuf[idx++];
			rlen += (pBuf[idx++] << 8);
			if ((rlen + 1) != len) 
			{
				break;
			}
			//pid
			int pID = 0;
			pID += pBuf[idx++];
			pID += (pBuf[idx++] << 8);
			pID += (pBuf[idx++] << 16);
			pID += (pBuf[idx++] << 24);
			//type
			pyfree::PType pType = (pyfree::PType)pBuf[idx++];
			//val
			float Value = float(0.0);
			unsigned char* fval = (unsigned char*)&Value;
			fval[3] = pBuf[idx++];
			fval[2] = pBuf[idx++];
			fval[1] = pBuf[idx++];
			fval[0] = pBuf[idx++];
			fval = NULL;
			//task id
			unsigned long taskID = 0;
			taskID += pBuf[idx++];
			taskID += (pBuf[idx++] << 8);
			taskID += (pBuf[idx++] << 16);
			taskID += (pBuf[idx++] << 24);
			//end
			unsigned char endflag = pBuf[idx++];
			if (0XFF != endflag)
			{
				Print_WARN("error end for frame data in AddFrameDef\r\n");
			}
			if (pyfree::OnYX == pType) 
			{
				Value = Value > 0 ? float(1.0) : float(0.0);
			}
			ToGchannelDatas->add(TransmitToGChannel(pyfree::OnGet, pID, pType, Value, taskID));
			
			//printf_s("read data 0XF5:pID[%d],pType[%d],val[%.3f],endflag[%02X]\n"
			//	,  pID, pType, Value, endflag);
			//test
			//m_WDData->addWDS(WDS(pType, pID,1.0));

		}
		break;
		case 0XF6://设值
		{
			int rlen = pBuf[idx++];
			rlen += (pBuf[idx++] << 8);
			if ((rlen + 1) != len) 
			{
				break;
			}
			//pid
			int pID = 0;
			pID += pBuf[idx++];
			pID += (pBuf[idx++] << 8);
			pID += (pBuf[idx++] << 16);
			pID += (pBuf[idx++] << 24);
			//type
			pyfree::PType pType = (pyfree::PType)pBuf[idx++];
			//val
			float Value = float(0.0);
			unsigned char* fval = (unsigned char*)&Value;
			fval[3] = pBuf[idx++];
			fval[2] = pBuf[idx++];
			fval[1] = pBuf[idx++];
			fval[0] = pBuf[idx++];
			fval = NULL;
			//task id
			unsigned long taskID = 0;
			taskID += pBuf[idx++];
			taskID += (pBuf[idx++] << 8);
			taskID += (pBuf[idx++] << 16);
			taskID += (pBuf[idx++] << 24);
			unsigned char endflag = pBuf[idx++];
			if (0XFF != endflag)
			{
				Print_WARN("error end for frame data in AddFrameDef\r\n");
			}
			if (pyfree::OnYX == pType) 
			{
				Value = Value > 0 ? float(1.0) : float(0.0);
			}
			ToGchannelDatas->add(TransmitToGChannel(pyfree::OnSet, pID, pType, Value, taskID));
			
			//Print_NOTICE("read data 0XF6:pID[%d],pType[%d],val[%.3f],endflag[%02X]\n"
			//	, pID, pType, Value, endflag);
		}
		break;
		default:
		{
			char warBuf[128] = { 0 };
			sprintf(warBuf,"MonitorData::AddFrameDef For Unkown Type(%02X)", type);
			#ifdef WIN32
			throw std::exception(warBuf);
			#else
			throw std::domain_error(warBuf);
			#endif
		}
		break;
		}
		return 1;
	}
	catch (const std::exception& e)
	{
		CLogger::createInstance()->Log(MsgError,
			"AddFrameDef(%s,%d) func error[%s]. [%s %s %d]"
			, pBuf, len
			, e.what()
			, __FILE__, __FUNCTION__, __LINE__);
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgFatal,
			"AddFrameDef(%s,%d) func error. [%s %s %d]"
			, pBuf, len
			, __FILE__, __FUNCTION__, __LINE__);
	}
	return -1;
};